	// verilator_coverage annotation
	`include "./AdamRiscv/define.vh"
	
	module alu(
 026326	    input  wire[3:0]     alu_ctrl,
 000387	    input  wire[31:0]    op_A,
 000649	    input  wire[31:0]    op_B,
 000639	    output reg[31:0]     alu_o,
%000007	    output wire          br_mark,
 506040	    input wire[31:0] ex_r_matrix_mopa[3:0],
%000286	    output wire [31:0] matrix_mopa_o [3:0]    
	);
	
%000070	reg[31:0] matrix_line_0;
%000060	reg[31:0] matrix_line_1;
%000080	reg[31:0] matrix_line_2;
%000073	reg[31:0] matrix_line_3;
	assign br_mark = (alu_ctrl == `JUMP)? 1 :
	                 (alu_ctrl == `NOTEQ || alu_ctrl == `SLT || alu_ctrl == `SLTU)?
	                 (alu_o != 0) : (alu_o == 0);
	 
	always @(alu_ctrl, op_A, op_B) begin
	    case (alu_ctrl)
%000000	        `AND        : alu_o = op_A & op_B;           
%000000	        `OR         : alu_o = op_A | op_B;           
 003422	        `ADD,`JUMP  : alu_o = op_A + op_B;           
 003292	        `SUB,`NOTEQ : alu_o = op_A - op_B;           
%000000	        `XOR        : alu_o = op_A ^ op_B;           
%000001	        `SLT,`SGE   : alu_o = ($signed(op_A)) < ($signed(op_B)) ? 32'b1 : 32'b0;   
%000000	        `SLTU,`SGEU : alu_o = op_A < op_B ? 32'b1 : 32'b0;   
%000000	        `SLL        : alu_o = op_A << op_B[4:0];
%000000	        `SRL        : alu_o = op_A >> op_B[4:0];
%000000	        `SRA        : alu_o = ($signed(op_A)) >>> op_B[4:0];
%000001		`MOPA       : begin
				matrix_line_3 = {
				ex_r_matrix_mopa[3][31:24] + op_A[31:24] * op_B[31:24],
				ex_r_matrix_mopa[3][23:16] + op_A[23:16] * op_B[31:24],
				ex_r_matrix_mopa[3][15:8] + op_A[15:8] * op_B[31:24],
				ex_r_matrix_mopa[3][7:0] + op_A[7:0] * op_B[31:24]
				};
				matrix_line_2 = {
				ex_r_matrix_mopa[2][31:24] + op_A[31:24] * op_B[23:16],
				ex_r_matrix_mopa[2][23:16] + op_A[23:16] * op_B[23:16],
				ex_r_matrix_mopa[2][15:8] + op_A[15:8] * op_B[23:16],
				ex_r_matrix_mopa[2][7:0] + op_A[7:0] * op_B[23:16]
				};
				matrix_line_1 = {
				ex_r_matrix_mopa[1][31:24] + op_A[31:24] * op_B[15:8],
				ex_r_matrix_mopa[1][23:16] + op_A[23:16] * op_B[15:8],
				ex_r_matrix_mopa[1][15:8] + op_A[15:8] * op_B[15:8],
				ex_r_matrix_mopa[1][7:0] + op_A[7:0] * op_B[15:8]
				};
				matrix_line_0 = {
				ex_r_matrix_mopa[0][31:24] + op_A[31:24] * op_B[7:0],
				ex_r_matrix_mopa[0][23:16] + op_A[23:16] * op_B[7:0],
				ex_r_matrix_mopa[0][15:8] + op_A[15:8] * op_B[7:0],
				ex_r_matrix_mopa[0][7:0] + op_A[7:0] * op_B[7:0]
				};
				alu_o = 0;
		
		end
 003285	        default: begin
			alu_o = 0;
			matrix_line_0 = 0;
			matrix_line_1 = 0;
			matrix_line_2 = 0;
			matrix_line_3 = 0;
		end
	    endcase
	end
	
	assign matrix_mopa_o[0] = matrix_line_0;
	assign matrix_mopa_o[1] = matrix_line_1;
	assign matrix_mopa_o[2] = matrix_line_2;
	assign matrix_mopa_o[3] = matrix_line_3;
	
	endmodule
	
